package eNodeB;

import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;

import radiowaves.RadioWaves;
import ue.UE;
import utils.Duration;
import xml.ParseXMLException;
import data.Data;

public class Fabrique {
	private static Fabrique singleton;

	private ENodeB eNodeB;
	private final Semaphore sem;
	private TheMap theMap;

	private final RadioWaves radioWave;
	private final Map<GregorianCalendar, List<Data>> mapDataTime = new HashMap<GregorianCalendar, List<Data>>();

	public static Fabrique getFabrique() {
		if (singleton == null) {
			singleton = new Fabrique();
		}
		return singleton;
	}

	private Fabrique() {
		sem = new Semaphore(1);
		radioWave = new RadioWaves(new Semaphore(1));

	}

	public ENodeB getEnodeB() {
		return eNodeB;
	}

	public void createMap(String id, double x, double y, String algorithm) {
		theMap = new TheMap(id, x, y, algorithm);
	}

	public TheMap getTheMap() {
		return theMap;
	}

	public void createEnodeB(int ressourceBlocks, double x, double y,
			double coverage, String begin, String end) {
		Duration duration = new Duration(begin, end);
		eNodeB = new ENodeB(sem, ressourceBlocks, x, y, coverage, radioWave,
				duration, mapDataTime);

	}

	public UE createUser(String id, double positionX, double positionY,
			String begin, String end) throws ParseXMLException {

		Duration duration = new Duration(begin, end);
		compareCalendar(eNodeB.getDuration(), duration, id, begin, end);
		UE ue = new UE(positionX, positionY, id, eNodeB, radioWave, duration);
		return ue;
	}

	public static void isInCalendar(Duration big, GregorianCalendar small)
			throws ParseXMLException {
		long beginBig = big.getBegin().getTimeInMillis();
		long endBig = big.getEnd().getTimeInMillis();
		long beginSmall = small.getTimeInMillis();
		if (beginSmall > endBig || beginSmall < beginBig) {
			throw new ParseXMLException("is not in field date ");
		}
	}

	public static void compareCalendar(Duration big, Duration small, String id,
			String begin, String end) throws ParseXMLException {
		long beginBig = big.getBegin().getTimeInMillis();
		long endBig = big.getEnd().getTimeInMillis();
		long beginSmall = small.getBegin().getTimeInMillis();
		long endSmall = small.getEnd().getTimeInMillis();
		if (beginBig > beginSmall) {
			throw new ParseXMLException("big begin > small small at id user= "
					+ id + " begin=" + begin);
		}
		if (endBig < endSmall) {
			throw new ParseXMLException("big end <  small end at id user= "
					+ id + " end=" + end);
		}

	}

	public void createData(String begin, String data, UE ue)
			throws ParseXMLException {
		Data dataClass = new Data(data, ue);
		GregorianCalendar beginCal = Duration.getCalendar(begin);
		isInCalendar(ue.getDuration(), beginCal);
		mapDataUser(beginCal, dataClass);

	}

	private void mapDataUser(GregorianCalendar begin, Data data) {
		List<Data> datas = mapDataTime.get(begin);
		if (datas == null) {
			datas = new ArrayList<Data>();
		}

		datas.add(data);
		mapDataTime.put(begin, datas);

	}

}
